package main

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/go-resty/resty/v2"
	"math/rand"
	"net/http"
	"time"
)

// 初始化有效的github token列表
func initValidGhuTokenMap() {
	for _, token := range configFile.CopilotConfig.Token {
		if getGithubApi(token) {
			// 有效的token
			validGhuTokenMap[token] = true
		}
	}
}

// 代理服务器返回copilot token
func proxyResp(c *gin.Context, respDataMap map[string]interface{}) {
	// 将map转换为JSON字符串
	responseJSON, _ := json.Marshal(respDataMap)
	// 请求成功统计
	successCount++
	// 将响应体作为JSON字符串返回
	c.Header("Content-Type", "application/json")
	c.String(http.StatusOK, string(responseJSON))
}

// 获取有效的 copilot token
func getCopilotToken() gin.HandlerFunc {
	return func(c *gin.Context) {
		//用户请求代理服务器的计数
		requestCount++
		//随机从有效的github token列表中获取一个token
		token := getRandomToken(validGhuTokenMap)
		//通过token取对应的copilot token的map数据
		if respDataMap, exists := getTokenData(token); exists {
			//没过期直接返回
			if !isTokenExpired(respDataMap) {
				proxyResp(c, respDataMap)
				return
			}
		}
		//过期了或者没取到，重新获取
		if getGithubApi(token) {
			proxyResp(c, copilotTokenMap[token])
		} else {
			// 重新获取失败，返回自定义消息 400
			diyBadRequest(c, 400, "can't get copilot token")
		}
	}
}

// 请求github api
func getGithubApi(token string) bool {
	// githubApi请求计数
	githubApiCount++
	// 设置请求头
	headers := map[string]string{
		"Authorization": "token " + token,
	}
	// 发起GET请求
	response, _ := resty.New().R().
		SetHeaders(headers).
		Get(configFile.CopilotConfig.GithubApiUrl)
	// 判断响应状态码
	if response.StatusCode() == http.StatusOK {
		// 响应状态码为200 OK
		respDataMap := map[string]interface{}{}
		_ = json.Unmarshal(response.Body(), &respDataMap)
		copilotTokenMap[token] = respDataMap
		return true
	} else {
		// 响应状态码不为200  map删除无效token
		delete(validGhuTokenMap, token)
		return false
	}
}

// 从map中获取github token对应的copilot token
func getTokenData(token string) (map[string]interface{}, bool) {
	respDataMap, exists := copilotTokenMap[token]
	return respDataMap, exists
}

// 检测copilot token是否过期
func isTokenExpired(respDataMap map[string]interface{}) bool {
	if expiresAt, ok := respDataMap["expires_at"].(float64); ok {
		currentTime := time.Now().Unix()
		expiresAtInt64 := int64(expiresAt)
		return expiresAtInt64 <= currentTime+60
	}
	return true
}

// 从map中随机获取一个github token
func getRandomToken(m map[string]bool) string {
	ghuTokenArray := make([]string, 0, len(m))
	for k := range m {
		ghuTokenArray = append(ghuTokenArray, k)
	}
	if len(ghuTokenArray) == 0 {
		return "" // 没有有效的token，返回空字符串
	}
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	randomIndex := r.Intn(len(ghuTokenArray))
	return ghuTokenArray[randomIndex]
}
